/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef ADLAPI_H
#define ADLAPI_H

struct ocfs2_super;

typedef void (adl_eviction_func)(int, void *);
struct adl_eviction_cb {
	struct list_head        ec_item;
	adl_eviction_func       *ec_func;
	void                    *ec_data;
};

enum adl_cb_type {
	ADL_QUERY_LOCK_CB = 0,
	ADL_UNLOCK_LOCK_CB,
	ADL_NUM_CB,
	ADL_RELEASE_TRUNCATE_LOG_CB,
};

typedef void (adl_net_request_cb_func)(u64, int, void *);
struct adl_net_request_cb {
	enum adl_cb_type net_cb_type;
	adl_net_request_cb_func *net_cb_func;
	void *net_cb_data;
	struct list_head net_cb_item;
};

#define ADL_LKF_NOQUEUE		0x00000001
#define ADL_LKF_NONBLOCK	0x00000002
#define ADL_LKF_USER_MODE		0x00000004
#define ADL_LKF_NEED_RECOVERY	0x00000008
#define ADL_LKF_PRINT_LOG	0x00000010

#define DISK_RETRY_TIME_MS 50
#define DISK_RETRY_MAX_MX (2 * 60 * 1000)
#define DISK_RETRY_MAX_TIMS (DISK_RETRY_MAX_MX / DISK_RETRY_TIME_MS)
#define DISK_PRINT_LOG_INTERNAL_MS (5 * 60 * 1000)  //5min

struct o2adl_private {
	struct adl_eviction_cb op_eviction_cb;
};

struct adl_ctxt {
	spinlock_t spinlock;
	char *name;
	u32 key;
	u16 node_num;

	/* block device, obtained from osb->sb->s_bdev during initialization. */
	struct block_device *bdev;

	/* protected by spinlock */
	int orphan;
	unsigned long live_nodes_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
	unsigned long recovery_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
	u32 **HBGen;

	struct list_head list;
	struct kref adl_refs;
	unsigned int num_joins;

	struct adl_debug_ctxt *adl_debug_ctxt;
	struct dentry *adl_debugfs_subroot;

	struct o2hb_callback_func adl_region_up;
	struct o2hb_callback_func adl_region_down;
	struct o2hb_callback_func adl_node_up;
	struct o2hb_callback_func adl_node_down;
	struct o2hb_callback_func adl_disk_timeout;
	struct list_head adl_eviction_callbacks;

	/* For async messages sending */
	struct list_head adl_net_request_callbacks;

	struct workqueue_struct *async_msg_worker;
	struct work_struct async_msg_work;
	struct list_head async_msg_list;
	spinlock_t async_msg_lock;

	struct list_head adl_domain_handlers;
};

struct adl_ctxt *adl_register_domain(char *name, u32 key,
		struct block_device *bdev);
void adl_unregister_domain(struct adl_ctxt *adl);
void adl_setup_eviction_cb(struct adl_eviction_cb *cb,  adl_eviction_func *f, void *data);
void adl_register_eviction_cb(struct adl_ctxt *adl,
		struct adl_eviction_cb *cb);
void adl_unregister_eviction_cb(struct adl_eviction_cb *cb);
int adl_initialize_lock_block(struct ocfs2_super *osb,
		u64 fe_lock_blkno);
void adl_clear_recovery_map(struct adl_ctxt *adl,
		unsigned int node_num);
void adl_set_recovery_map(struct adl_ctxt *adl,
		unsigned int node_num);
int adl_other_nodes_pending(struct adl_ctxt *adl, u64 blkno, int offset);
void adl_setup_net_request_cb(struct adl_net_request_cb *cb,
		adl_net_request_cb_func *f,
		enum adl_cb_type type,
		void *data);
void adl_register_net_request_cb(struct adl_ctxt *adl,
		struct adl_net_request_cb *cb);
void adl_unregister_net_request_cb(struct adl_net_request_cb *cb);

#endif /* ADLAPI_H */
